package com.corpgovernment.organization.operatelog.service.aspect;


import com.corpgovernment.common.operatelog.OperateLog;
import com.corpgovernment.common.operatelog.bo.OprerateLogBo;
import com.corpgovernment.common.operatelog.constant.OperateLogContant;
import com.corpgovernment.organization.operatelog.service.OperateLogService;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @ClassName: OperateLogAspect
 * @description: TODO
 * @author: jiang.luo
 * @date: Created in 19:42 2020/1/3
 * @Version: 1.0
 **/
@Slf4j
@Aspect
@Component
public class OperateLogAspect {
    @Autowired
    private OperateLogService operateLogService;

    /**
     * 这里我们使用注解的形式
     * 当然，我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method
     * 切点表达式:   execution(...)
     */
    @Pointcut("@annotation(com.corpgovernment.common.operatelog.OperateLog)")
    public void logPointCut() {
    }

    /**
     * 环绕通知 @Around  ， 当然也可以使用 @Before (前置通知)  @After (后置通知)
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        ProceedingJoinPoint old = point;
        Object olds = convertParams(old, OperateLogContant.BEFORE,null);
        Object result = point.proceed();
        Object points = convertParams(point, OperateLogContant.AFTER,result);
        operateLogService.saveLog(olds, points);
        return result;
    }

    /**
     * 转换类型
     *
     * @param point
     */
    private Object convertParams(JoinPoint point, Integer params, Object types) {
        Object o = null;
        try {
            MethodSignature signature = (MethodSignature) point.getSignature();
            Method method = signature.getMethod();
            OprerateLogBo sysLogBO = new OprerateLogBo();
            OperateLog sysLog = method.getAnnotation(OperateLog.class);
            if (sysLog != null) {
                //注解上的描述
                sysLogBO.setRemark(sysLog.value());
            }
            //请求的 类名、方法名
            String className = point.getTarget().getClass().getName();
            String methodName = signature.getName();
            sysLogBO.setClassName(className);
            sysLogBO.setMethodName(methodName);
            //请求的参数
            Object[] args = point.getArgs();

            sysLogBO.setParams(JsonUtils.toJsonString(args));
            o = operateLogService.convertParams(sysLogBO, params,types);
        } catch (Exception e) {
            log.error("转化类型失败！原因:{}", e.getMessage(), e);
            return null;
        }
        return o;
    }

}
